
package com.csscis.ssm.core.feature.orm.dialect;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author QingHe
 * @since 2014年5月18日 下午1:32:42
 **/
public class MSPageHepler extends DialectHelper {

    /**
     * 生成返回查询总数的sql语句
     *
     * @param querySelect SQL语句
     * @return            生成的SQL语句
     */
    public static String getCountString(String querySelect) {

        querySelect = getLineSql(querySelect);
        int orderIndex = getLastOrderInsertPoint(querySelect);

        int formIndex = getFirstFromInsertPoint(querySelect);
        String select = querySelect.substring(0, formIndex);

        // 如果SELECT 中包含 DISTINCT 只能在外层包含COUNT
        if (select.toLowerCase().indexOf("select distinct") != -1
                || querySelect.toLowerCase().indexOf("group by") != -1) {
            return new StringBuffer(querySelect.length())
                    .append("select count(1) count from (")
                    .append(querySelect.substring(0, orderIndex))
                    .append(" ) t")
                    .toString();
        } else {
            return new StringBuffer(querySelect.length())
                    .append("select count(1) count ")
                    .append(querySelect.substring(formIndex, orderIndex))
                    .toString();
        }
    }

    //FIXME order by 前后应有空白
    /**
     * 得到最后一个Order By的插入点位置
     *
     * @param querySelect 待查找的SQL语句
     * @return            最后一个Order By插入点的位置
     */
    private static int getLastOrderInsertPoint(String querySelect) {

        int orderIndex = querySelect.toLowerCase().lastIndexOf("order by");
        if (orderIndex == -1 || !isBracketCanPartnership(querySelect.substring(orderIndex, querySelect.length()))) {
            throw new RuntimeException("My SQL 分页必须要有Order by 语句!");
        }
        return orderIndex;
    }

    //FIXME select 前后应有空白
    /**
     * 得到分页的SQL
     *
     * @param offset 偏移量
     * @param limit  位置
     * @return       分页SQL
     */
    public static String getLimitString(String querySelect, int offset, int limit) {

        querySelect = getLineSql(querySelect);
        int selectIndex = querySelect.toUpperCase().lastIndexOf("SELECT");
        if (selectIndex > -1) {
            querySelect = querySelect.substring(0, selectIndex) + "SELECT TOP " + (limit + offset)
                    + querySelect.substring(selectIndex + 6);
        }
        String sql = "SELECT * FROM(SELECT ROW_NUMBER () OVER (ORDER BY getdate()) rownum,* FROM( " + querySelect
                + " ) A ) B WHERE B.rownum > " + offset + " AND B.rownum <= "
                + (limit + offset);
        return sql;

    }

    /**
     * 得到SQL第一个正确的FROM的的插入点
     */
    private static int getFirstFromInsertPoint(String querySelect) {

        String regex = "\\s+FROM\\s+";
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(querySelect);
        while (matcher.find()) {
            int fromStartIndex = matcher.start(0);
            String text = querySelect.substring(0, fromStartIndex);
            if (isBracketCanPartnership(text)) {
                return fromStartIndex;
            }
        }
        return 0;
    }

    /**
     * 判断括号"("、")"数量是否相同，不会判断嵌套是否正确
     *
     * @param text 要判断的文本
     * @return     如果左右小括号数量匹配，返回TRUE,否则返回FALSE
     */
    private static boolean isBracketCanPartnership(String text) {

        if (text == null || (getIndexOfCount(text, '(') != getIndexOfCount(text, ')'))) {
            return false;
        }
        return true;
    }

}
